const md5 = require('md5')
const xml2js = require('xml2js')
const Parser = new xml2js.Parser()
const uuid = require('uuid/v4')
const randomChar = uuid().toString().replace(/-/g, '') //随机生成的字符串

const request = require('request')
const prepay_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'

module.exports = async function prepay(openid, orderID, requestIP, total_fee) {
    const obj = {
        appid: 'wx24a21b47e8d32f78',
        body: 'Qolay便利服务商品',
        mch_id: 1529114461,
        nonce_str: randomChar,
        openid: openid,
        notify_url: 'http://192.168.10.155:5757/mpApi/payReturn',
        // notify_url: 'http://wx.2xur7.cn/weapp/payReturn',
        out_trade_no: orderID,
        spbill_create_ip: requestIP,
        total_fee: total_fee,
        trade_type: 'JSAPI'
    }
    let arr = Object.keys(obj).sort().map(item => {
        return `${item}=${obj[item]}`;
    });
    // 这里拼接签名字符串的时候一定要注意: 商户的key是要单独拿出来拼在最后面的
    let str = arr.join('&') + '&key=f2ec4b1440f6f15e1a6a5dca0bb704b3';

    obj.sign = getSign(str);
    let res;
    try {
        // 调用微信统一下单接口拿到 prepay_id
        res = await wechatPay(obj);
        let {
            prepay_id
        } = res;
        if (prepay_id) {
            res = getClientPayConfig(prepay_id)
        }
        // console.log(res);
    } catch (e) {
        res = e;
    }
    return res;
}


/**
 * 统一下单 prepay_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
 * @param {Object} obj 调用统一下单的必须参数
 */
const wechatPay = (obj) => {
    let xml = json2xml(obj);
    //   console.log(xml)
    return new Promise((resolve, reject) => {
        // 这里用了reques库,不熟悉的同学可以看看相关文档 https://github.com/request/request
        // 总之就是向微信的统一下单接口提交一个xml
        request({
            method: 'POST',
            url: prepay_url,
            body: xml
        }, (err, res, body) => {
            if (err) {
                reject(err);
            } else {
                //如果成功即可得到微信返回参数
                // console.log(body);
                let obj = parseXml(body).xml;
                resolve(obj);
            }
        });
    });
}


/**
 * 对指定字符串进行md5加密
 * @param {String} str 
 */
const getSign = (str) => {
    return md5(str).toUpperCase();
}

/**
 * 转化xml用了xml2js库  
    https://github.com/Leonidas-from-XIV/node-xml2js
 * @param {Object} obj 
 */
const json2xml = (obj) => {
    let builder = new xml2js.Builder({
        headless: true,
        allowSurrogateChars: true,
        rootName: 'xml',
        cdata: true
    });
    var xml = builder.buildObject(obj);
    return xml;
}

const parseXml = (xml) => {
    let {
        parseString
    } = xml2js;
    let res;
    parseString(xml, {
        trim: true,
        explicitArray: false
    }, function (err, result) {
        res = result;
    });
    return res;
}

/**
 * 生成指定长度的随机数
 * @param {*int} len 
 */
/* 
const get_nonce_str = (len) => {
  let str = '';
  while (str.length < len) {
    str += Math.random().toString(36).slice(2);
  }
  return str.slice(-len);
} */
const getClientPayConfig = (prepay_id) => {
    let obj = {
        appId: 'wx24a21b47e8d32f78',
        timeStamp: String(Math.floor(Date.now() / 1000)),
        nonceStr: randomChar,
        package: 'prepay_id=' + prepay_id,
        signType: 'MD5'
    }
    let arr = Object.keys(obj).sort().map(item => {
        return `${item}=${obj[item]}`;
    });
    let str = arr.join('&') + '&key=f2ec4b1440f6f15e1a6a5dca0bb704b3';
    obj.paySign = getSign(str);
    return obj;
}